package com.jpatest.demo.Redis;

import org.springframework.cache.Cache;
import org.springframework.data.redis.cache.RedisCache;

import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;

public class RedisAndLocalCache implements Cache {
    //本地缓存
    ConcurrentHashMap<Object, Object> local  = new ConcurrentHashMap<Object, Object>();

    RedisCache redisCache;
    TwoLevelCacheManager cacheManager;

    public RedisAndLocalCache(RedisCache redisCache, TwoLevelCacheManager cacheManager){
        this.redisCache = redisCache;
        this.cacheManager = cacheManager;
    }

    @Override
    public String getName() {
        return redisCache.getName();
    }

    @Override
    public Object getNativeCache() {
        return redisCache.getNativeCache();
    }

    @Override
    public ValueWrapper get(Object key) {
        //一级缓存先取，如果有直接返回；否则二级缓存取，然后存入一级缓存
        ValueWrapper wrapper = (ValueWrapper)local.get(key);
        if(wrapper!=null){
            return wrapper;
        }else{
            wrapper = (ValueWrapper)redisCache.get(key);
            if(wrapper!=null){
                local.put(key,wrapper);
            }
            return wrapper;
        }
    }

    @Override
    public <T> T get(Object o, Class<T> aClass) {
        return null;
    }

    @Override
    public <T> T get(Object o, Callable<T> callable) {
        return null;
    }

    @Override
    public void put(Object key, Object value) {
        redisCache.put(key, value);
        updateOtherJVM(key, value);
    }

    @Override
    public ValueWrapper putIfAbsent(Object o, Object o1) {
        return null;
    }

    @Override
    public void evict(Object key) {
        redisCache.evict(key);
        clearOtherJVM(key);
    }

    @Override
    public void clear() {

    }

    protected void clearOtherJVM(Object key){
        cacheManager.pulishMessage("clear", redisCache.getName(), key);
    }

    protected void updateOtherJVM(Object key, Object value){
        cacheManager.pulishMessage("update", redisCache.getName(), key);
    }

    public void clearLocal(Object key){
        this.local.remove(key);
    }

    public void updateLocal(Object key){
        this.local.put(key,(ValueWrapper)redisCache.get(key));
    }
}
